home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / String.java < prev    next >
Text File  |  1998-09-22  |  55KB  |  1,532 lines

  1. /*
  2.  * @(#)String.java    1.85 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.lang;
  16.  
  17. import java.util.Hashtable;
  18. import java.util.Locale;
  19. import sun.io.ByteToCharConverter;
  20. import sun.io.CharToByteConverter;
  21. import java.io.CharConversionException;
  22. import java.io.UnsupportedEncodingException;
  23.  
  24. /**
  25.  * The <code>String</code> class represents character strings. All 
  26.  * string literals in Java programs, such as <code>"abc"</code>, are 
  27.  * implemented as instances of this class. 
  28.  * <p>
  29.  * Strings are constant; their values cannot be changed after they 
  30.  * are created. String buffers support mutable strings.
  31.  * Because String objects are immutable they can be shared. For example:
  32.  * <p><blockquote><pre>
  33.  *     String str = "abc";
  34.  * </pre></blockquote><p>
  35.  * is equivalent to:
  36.  * <p><blockquote><pre>
  37.  *     char data[] = {'a', 'b', 'c'};
  38.  *     String str = new String(data);
  39.  * </pre></blockquote><p>
  40.  * Here are some more examples of how strings can be used:
  41.  * <p><blockquote><pre>
  42.  *     System.out.println("abc");
  43.  *     String cde = "cde";
  44.  *     System.out.println("abc" + cde);
  45.  *     String c = "abc".substring(2,3);
  46.  *     String d = cde.substring(1, 2);
  47.  * </pre></blockquote>
  48.  * <p>
  49.  * The class <code>String</code> includes methods for examining 
  50.  * individual characters of the sequence, for comparing strings, for 
  51.  * searching strings, for extracting substrings, and for creating a 
  52.  * copy of a string with all characters translated to uppercase or to 
  53.  * lowercase. 
  54.  * <p>
  55.  * The Java language provides special support for the string 
  56.  * concatentation operator ( + ), and for conversion of 
  57.  * other objects to strings. String concatenation is implemented 
  58.  * through the <code>StringBuffer</code> class and its 
  59.  * <code>append</code> method.
  60.  * String conversions are implemented through the method 
  61.  * <code>toString</code>, defined by <code>Object</code> and 
  62.  * inherited by all classes in Java. For additional information on 
  63.  * string concatenation and conversion, see Gosling, Joy, and Steele, 
  64.  * <i>The Java Language Specification</i>. 
  65.  *
  66.  * @author  Lee Boynton
  67.  * @author  Arthur van Hoff
  68.  * @version 1.85, 07/01/98
  69.  * @see     java.lang.Object#toString()
  70.  * @see     java.lang.StringBuffer
  71.  * @see     java.lang.StringBuffer#append(boolean)
  72.  * @see     java.lang.StringBuffer#append(char)
  73.  * @see     java.lang.StringBuffer#append(char[])
  74.  * @see     java.lang.StringBuffer#append(char[], int, int)
  75.  * @see     java.lang.StringBuffer#append(double)
  76.  * @see     java.lang.StringBuffer#append(float)
  77.  * @see     java.lang.StringBuffer#append(int)
  78.  * @see     java.lang.StringBuffer#append(long)
  79.  * @see     java.lang.StringBuffer#append(java.lang.Object)
  80.  * @see     java.lang.StringBuffer#append(java.lang.String)
  81.  * @since   JDK1.0
  82.  */
  83. public final
  84. class String implements java.io.Serializable {
  85.     /** The value is used for character storage. */
  86.     private char value[];
  87.  
  88.     /** The offset is the first index of the storage that is used. */
  89.     private int offset;
  90.  
  91.     /** The count is the number of characters in the String. */
  92.     private int count;
  93.  
  94.     /** use serialVersionUID from JDK 1.0.2 for interoperability */
  95.     private static final long serialVersionUID = -6849794470754667710L;
  96.  
  97.     /**
  98.      * Allocates a new <code>String</code> containing no characters. 
  99.      */
  100.     public String() {
  101.     value = new char[0];
  102.     }
  103.  
  104.     /**
  105.      * Allocates a new string that contains the same sequence of 
  106.      * characters as the string argument. 
  107.      *
  108.      * @param   value   a <code>String</code>.
  109.      */
  110.     public String(String value) {
  111.     count = value.length();
  112.     this.value = new char[count];
  113.     value.getChars(0, count, this.value, 0);
  114.     }
  115.  
  116.     /**
  117.      * Allocates a new <code>String</code> so that it represents the 
  118.      * sequence of characters currently contained in the character array 
  119.      * argument. 
  120.      *
  121.      * @param  value   the initial value of the string.
  122.      */
  123.     public String(char value[]) {
  124.     this.count = value.length;
  125.     this.value = new char[count];
  126.     System.arraycopy(value, 0, this.value, 0, count);
  127.     }
  128.  
  129.     /**
  130.      * Allocates a new <code>String</code> that contains characters from 
  131.      * a subarray of the character array argument. The <code>offset</code> 
  132.      * argument is the index of the first character of the subarray and 
  133.      * the <code>count</code> argument specifies the length of the 
  134.      * subarray. 
  135.      *
  136.      * @param      value    array that is the source of characters.
  137.      * @param      offset   the initial offset.
  138.      * @param      count    the length.
  139.      * @exception  StringIndexOutOfBoundsException  if the <code>offset</code>
  140.      *               and <code>count</code> arguments index characters outside
  141.      *               the bounds of the <code>value</code> array.
  142.      */
  143.     public String(char value[], int offset, int count) {
  144.     if (offset < 0) {
  145.         throw new StringIndexOutOfBoundsException(offset);
  146.     }
  147.     if (count < 0) {
  148.         throw new StringIndexOutOfBoundsException(count);
  149.     }
  150.     // Note: offset or count might be near -1>>>1.
  151.     if (offset > value.length - count) {
  152.         throw new StringIndexOutOfBoundsException(offset + count);
  153.     }
  154.  
  155.     this.value = new char[count];
  156.     this.count = count;
  157.     System.arraycopy(value, offset, this.value, 0, count);
  158.     }
  159.  
  160.     /**
  161.      * Allocates a new <code>String</code> constructed from a subarray 
  162.      * of an array of 8-bit integer values. 
  163.      * <p>
  164.      * The <code>offset</code> argument is the index of the first byte 
  165.      * of the subarray, and the <code>count</code> argument specifies the 
  166.      * length of the subarray. 
  167.      * <p>
  168.      * Each <code>byte</code> in the subarray is converted to a 
  169.      * <code>char</code> as specified in the method above. 
  170.      *
  171.      * @deprecated This method does not properly convert bytes into characters.
  172.      * As of JDK 1.1, the preferred way to do this is via the
  173.      * <code>String</code> constructors that take a character-encoding name or
  174.      * that use the platform's default encoding.
  175.      *
  176.      * @param      ascii     the bytes to be converted to characters.
  177.      * @param      hibyte    the top 8 bits of each 16-bit Unicode character.
  178.      * @param      offset    the initial offset.
  179.      * @param      count     the length.
  180.      * @exception  StringIndexOutOfBoundsException  if the <code>offset</code>
  181.      *               or <code>count</code> argument is invalid.
  182.      * @see        java.lang.String#String(byte[], int)
  183.      * @see        java.lang.String#String(byte[], int, int, java.lang.String)
  184.      * @see        java.lang.String#String(byte[], int, int)
  185.      * @see        java.lang.String#String(byte[], java.lang.String)
  186.      * @see        java.lang.String#String(byte[])
  187.      */
  188.     public String(byte ascii[], int hibyte, int offset, int count) {
  189.     if (offset < 0) {
  190.         throw new StringIndexOutOfBoundsException(offset);
  191.     }
  192.     if (count < 0) {
  193.         throw new StringIndexOutOfBoundsException(count);
  194.     }
  195.     // Note: offset or count might be near -1>>>1.
  196.     if (offset > ascii.length - count) {
  197.         throw new StringIndexOutOfBoundsException(offset + count);
  198.     }
  199.  
  200.     char value[] = new char[count];
  201.     this.count = count;
  202.     this.value = value;
  203.  
  204.     if (hibyte == 0) {
  205.         for (int i = count ; i-- > 0 ;) {
  206.         value[i] = (char) (ascii[i + offset] & 0xff);
  207.         }
  208.     } else {
  209.         hibyte <<= 8;
  210.         for (int i = count ; i-- > 0 ;) {
  211.         value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
  212.         }
  213.     }
  214.     }
  215.  
  216.     /**
  217.      * Allocates a new <code>String</code> containing characters 
  218.      * constructed from an array of 8-bit integer values. Each character 
  219.      * <i>c</i>in the resulting string is constructed from the 
  220.      * corresponding component <i>b</i> in the byte array such that:
  221.      * <p><blockquote><pre>
  222.      *     <b><i>c</i></b> == (char)(((hibyte & 0xff) << 8)
  223.      *                         | (<b><i>b</i></b> & 0xff))
  224.      * </pre></blockquote>
  225.      *
  226.      * @deprecated This method does not properly convert bytes into characters.
  227.      * As of JDK 1.1, the preferred way to do this is via the
  228.      * <code>String</code> constructors that take a character-encoding name or
  229.      * that use the platform's default encoding.
  230.      *
  231.      * @param      ascii    the bytes to be converted to characters.
  232.      * @param      hibyte   the top 8 bits of each 16-bit Unicode character.
  233.      * @see        java.lang.String#String(byte[], int, int, java.lang.String)
  234.      * @see        java.lang.String#String(byte[], int, int)
  235.      * @see        java.lang.String#String(byte[], java.lang.String)
  236.      * @see        java.lang.String#String(byte[])
  237.      */
  238.     public String(byte ascii[], int hibyte) {
  239.     this(ascii, hibyte, 0, ascii.length);
  240.     }
  241.  
  242.     /**
  243.      * Construct a new <code>String</code> by converting the specified
  244.      * subarray of bytes using the specified character-encoding converter.  The
  245.      * length of the new <code>String</code> is a function of the encoding, and
  246.      * hence may not be equal to the length of the subarray.
  247.      *
  248.      * @param  bytes   The bytes to be converted into characters
  249.      * @param  offset  Index of the first byte to convert
  250.      * @param  length  Number of bytes to convert
  251.      * @param  btc     A ByteToCharConverter
  252.      */
  253.     private String(byte bytes[], int offset, int length,
  254.            ByteToCharConverter btc)
  255.     {
  256.     int estCount = btc.getMaxCharsPerByte() * length;
  257.     value = new char[estCount];
  258.  
  259.         try {
  260.         count = btc.convert(bytes, offset, offset+length,
  261.                 value, 0, estCount);
  262.         count += btc.flush(value, btc.nextCharIndex(), estCount);
  263.     }
  264.     catch (CharConversionException x) {
  265.         count = btc.nextCharIndex();
  266.     }
  267.  
  268.     if (count < estCount) {
  269.         // A multi-byte format was used:  Trim the char array.
  270.         char[] trimValue = new char[count];
  271.         System.arraycopy(value, 0, trimValue, 0, count);
  272.         value = trimValue;
  273.     }
  274.     }
  275.  
  276.     /**
  277.      * Construct a new <code>String</code> by converting the specified
  278.      * subarray of bytes using the specified character encoding.  The length of
  279.      * the new <code>String</code> is a function of the encoding, and hence may
  280.      * not be equal to the length of the subarray.
  281.      *
  282.      * @param  bytes   The bytes to be converted into characters
  283.      * @param  offset  Index of the first byte to convert
  284.      * @param  length  Number of bytes to convert
  285.      * @param  enc     The name of a character encoding
  286.      *
  287.      * @exception  UnsupportedEncodingException
  288.      *             If the named encoding is not supported
  289.      * @since      JDK1.1
  290.      */
  291.     public String(byte bytes[], int offset, int length, String enc)
  292.     throws UnsupportedEncodingException
  293.     {
  294.     this(bytes, offset, length, ByteToCharConverter.getConverter(enc));
  295.     }
  296.  
  297.     /**
  298.      * Construct a new <code>String</code> by converting the specified array
  299.      * of bytes using the specified character encoding.  The length of the new
  300.      * <code>String</code> is a function of the encoding, and hence may not be
  301.      * equal to the length of the byte array.
  302.      *
  303.      * @param  bytes   The bytes to be converted into characters
  304.      * @param  enc     A character-encoding name
  305.      *
  306.      * @exception  UnsupportedEncodingException
  307.      *             If the named encoding is not supported
  308.      * @since      JDK1.1
  309.      */
  310.     public String(byte bytes[], String enc)
  311.     throws UnsupportedEncodingException
  312.     {
  313.     this(bytes, 0, bytes.length, enc);
  314.     }
  315.  
  316.     /**
  317.      * Construct a new <code>String</code> by converting the specified
  318.      * subarray of bytes using the platform's default character encoding.  The
  319.      * length of the new <code>String</code> is a function of the encoding, and
  320.      * hence may not be equal to the length of the subarray.
  321.      *
  322.      * @param  bytes   The bytes to be converted into characters
  323.      * @param  offset  Index of the first byte to convert
  324.      * @param  length  Number of bytes to convert
  325.      * @since  JDK1.1
  326.      */
  327.     public String(byte bytes[], int offset, int length) {
  328.     this(bytes, offset, length, ByteToCharConverter.getDefault());
  329.     }
  330.  
  331.     /**
  332.      * Construct a new <code>String</code> by converting the specified array
  333.      * of bytes using the platform's default character encoding.  The length of
  334.      * the new <code>String</code> is a function of the encoding, and hence may
  335.      * not be equal to the length of the byte array.
  336.      *
  337.      * @param  bytes   The bytes to be converted into characters
  338.      * @since  JDK1.1
  339.      */
  340.     public String(byte bytes[]) {
  341.     this(bytes, 0, bytes.length, ByteToCharConverter.getDefault());
  342.     }
  343.  
  344.     /**
  345.      * Allocates a new string that contains the sequence of characters 
  346.      * currently contained in the string buffer argument. 
  347.      *
  348.      * @param   buffer   a <code>StringBuffer</code>.
  349.      */
  350.     public String (StringBuffer buffer) { 
  351.     synchronized(buffer) { 
  352.         buffer.setShared();
  353.         this.value = buffer.getValue();
  354.         this.offset = 0;
  355.         this.count = buffer.length();
  356.     }
  357.     }
  358.     
  359.     // Private constructor which shares value array for speed.
  360.     private String(int offset, int count, char value[]) {
  361.     this.value = value;
  362.     this.offset = offset;
  363.     this.count = count;
  364.     }
  365.  
  366.     /**
  367.      * Returns the length of this string.
  368.      * The length is equal to the number of 16-bit
  369.      * Unicode characters in the string.
  370.      *
  371.      * @return  the length of the sequence of characters represented by this
  372.      *          object.
  373.      */
  374.     public int length() {
  375.     return count;
  376.     }
  377.  
  378.     /**
  379.      * Returns the character at the specified index. An index ranges
  380.      * from <code>0</code> to <code>length() - 1</code>.
  381.      *
  382.      * @param      index   the index of the character.
  383.      * @return     the character at the specified index of this string.
  384.      *             The first character is at index <code>0</code>.
  385.      * @exception  StringIndexOutOfBoundsException  if the index is out of
  386.      *               range.
  387.      */
  388.     public char charAt(int index) {
  389.     if ((index < 0) || (index >= count)) {
  390.         throw new StringIndexOutOfBoundsException(index);
  391.     }
  392.     return value[index + offset];
  393.     }
  394.  
  395.     /**
  396.      * Copies characters from this string into the destination character array. 
  397.      * <p>
  398.      * The first character to be copied is at index <code>srcBegin</code>; 
  399.      * the last character to be copied is at index <code>srcEnd-1</code> 
  400.      * (thus the total number of characters to be copied is 
  401.      * <code>srcEnd-srcBegin</code>). The characters are copied into the 
  402.      * subarray of <code>dst</code> starting at index <code>dstBegin</code> 
  403.      * and ending at index: 
  404.      * <p><blockquote><pre>
  405.      *     dstbegin + (srcEnd-srcBegin) - 1
  406.      * </pre></blockquote>
  407.      *
  408.      * @param      srcBegin   index of the first character in the string
  409.      *                        to copy.
  410.      * @param      srcEnd     index after the last character in the string
  411.      *                        to copy.
  412.      * @param      dst        the destination array.
  413.      * @param      dstBegin   the start offset in the destination array.
  414.      * @exception StringIndexOutOfBoundsException If srcBegin or srcEnd is out 
  415.      *              of range, or if srcBegin is greater than the srcEnd.
  416.      */
  417.     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
  418.     if (srcBegin < 0) {
  419.         throw new StringIndexOutOfBoundsException(srcBegin);
  420.     } 
  421.     if (srcEnd > count) {
  422.         throw new StringIndexOutOfBoundsException(srcEnd);
  423.     } 
  424.     if (srcBegin > srcEnd) {
  425.         throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
  426.     }
  427.     System.arraycopy(value, offset + srcBegin, dst, dstBegin, srcEnd - srcBegin);
  428.     }
  429.  
  430.     /**
  431.      * Copies characters from this string into the destination byte 
  432.      * array. Each byte receives the 8 low-order bits of the 
  433.      * corresponding character. 
  434.      * <p>
  435.      * The first character to be copied is at index <code>srcBegin</code>; 
  436.      * the last character to be copied is at index <code>srcEnd-1</code>. 
  437.      * The total number of characters to be copied is 
  438.      * <code>srcEnd-srcBegin</code>. The characters, converted to bytes, 
  439.      * are copied into the subarray of <code>dst</code> starting at index 
  440.      * <code>dstBegin</code> and ending at index: 
  441.      * <p><blockquote><pre>
  442.      *     dstbegin + (srcEnd-srcBegin) - 1
  443.      * </pre></blockquote>
  444.      *
  445.      * @deprecated This method does not properly convert characters into bytes.
  446.      * As of JDK 1.1, the preferred way to do this is via the
  447.      * <code>getBytes(String enc)</code> method, which takes a
  448.      * character-encoding name, or the <code>getBytes()</code> method, which
  449.      * uses the platform's default encoding.
  450.      *
  451.      * @param      srcBegin   index of the first character in the string
  452.      *                        to copy.
  453.      * @param      srcEnd     index after the last character in the string
  454.      *                        to copy.
  455.      * @param      dst        the destination array.
  456.      * @param      dstBegin   the start offset in the destination array.
  457.      * @exception StringIndexOutOfBoundsException  if srcBegin or srcEnd is out 
  458.      *              of range, or if srcBegin is greater than srcEnd.
  459.      */
  460.     public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
  461.     if (srcBegin < 0) {
  462.         throw new StringIndexOutOfBoundsException(srcBegin);
  463.     } 
  464.     if (srcEnd > count) {
  465.         throw new StringIndexOutOfBoundsException(srcEnd);
  466.     } 
  467.     if (srcBegin > srcEnd) {
  468.         throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
  469.     }
  470.      int j = dstBegin;
  471.      int n = offset + srcEnd;
  472.      int i = offset + srcBegin;
  473.     char[] val = value;   /* avoid getfield opcode */
  474.  
  475.      while (i < n) {
  476.          dst[j++] = (byte)val[i++];
  477.      }
  478.     }
  479.  
  480.     /**
  481.      * Apply the specified character-encoding converter to this String,
  482.      * storing the resulting bytes into a new byte array.
  483.      *
  484.      * @param  ctb  A CharToByteConverter
  485.      * @return      The resultant byte array
  486.      */
  487.     private byte[] getBytes(CharToByteConverter ctb) {
  488.     ctb.reset();
  489.     int estLength = ctb.getMaxBytesPerChar() * count;
  490.     byte[] result = new byte[estLength];
  491.     int length;
  492.  
  493.     try {
  494.         length = ctb.convert(value, offset, offset + count,
  495.                  result, 0, estLength);
  496.         length += ctb.flush(result, ctb.nextByteIndex(), estLength);
  497.     } catch (CharConversionException e) {
  498.         length = ctb.nextByteIndex();
  499.     }
  500.  
  501.     if (length < estLength) {
  502.         // A short format was used:  Trim the byte array.
  503.         byte[] trimResult = new byte[length];
  504.         System.arraycopy(result, 0, trimResult, 0, length);
  505.         return trimResult;
  506.     }
  507.     else {
  508.         return result;
  509.     }
  510.     }
  511.  
  512.     /**
  513.      * Convert this <code>String</code> into bytes according to the specified
  514.      * character encoding, storing the result into a new byte array.
  515.      *
  516.      * @param  enc  A character-encoding name
  517.      * @return      The resultant byte array
  518.      *
  519.      * @exception  UnsupportedEncodingException
  520.      *             If the named encoding is not supported
  521.      * @since      JDK1.1
  522.      */
  523.     public byte[] getBytes(String enc)
  524.     throws UnsupportedEncodingException
  525.     {
  526.     return getBytes(CharToByteConverter.getConverter(enc));
  527.     }
  528.  
  529.     /**
  530.      * Convert this <code>String</code> into bytes according to the platform's
  531.      * default character encoding, storing the result into a new byte array.
  532.      *
  533.      * @return  the resultant byte array.
  534.      * @since   JDK1.1
  535.      */
  536.     public byte[] getBytes() {
  537.     return getBytes(CharToByteConverter.getDefault());
  538.     }
  539.  
  540.     /**
  541.      * Compares this string to the specified object.
  542.      * The result is <code>true</code> if and only if the argument is not 
  543.      * <code>null</code> and is a <code>String</code> object that represents 
  544.      * the same sequence of characters as this object. 
  545.      *
  546.      * @param   anObject   the object to compare this <code>String</code>
  547.      *                     against.
  548.      * @return  <code>true</code> if the <code>String </code>are equal;
  549.      *          <code>false</code> otherwise.
  550.      * @see     java.lang.String#compareTo(java.lang.String)
  551.      * @see     java.lang.String#equalsIgnoreCase(java.lang.String)
  552.      */
  553.     public boolean equals(Object anObject) {
  554.     if (this == anObject) {
  555.         return true;
  556.     }
  557.     if ((anObject != null) && (anObject instanceof String)) {
  558.         String anotherString = (String)anObject;
  559.         int n = count;
  560.         if (n == anotherString.count) {
  561.         char v1[] = value;
  562.         char v2[] = anotherString.value;
  563.         int i = offset;
  564.         int j = anotherString.offset;
  565.         while (n-- != 0) {
  566.             if (v1[i++] != v2[j++]) {
  567.             return false;
  568.             }
  569.         }
  570.         return true;
  571.         }
  572.     }
  573.     return false;
  574.     }
  575.  
  576.     /**
  577.      * Compares this String to another object.
  578.      * The result is <code>true</code> if and only if the argument is not 
  579.      * <code>null</code> and is a <code>String</code> object that represents 
  580.      * the same sequence of characters as this object, where case is ignored. 
  581.      * <p>
  582.      * Two characters are considered the same, ignoring case, if at 
  583.      * least one of the following is true: 
  584.      * <ul>
  585.      * <li>The two characters are the same (as compared by the <code>==</code> 
  586.      *     operator). 
  587.      * <li>Applying the method <code>Character.toUppercase</code> to each 
  588.      *     character produces the same result. 
  589.      * <li>Applying the method <code>Character.toLowercase</code> to each 
  590.      *     character produces the same result. 
  591.      * </ul>
  592.      * <p>
  593.      * Two sequences of characters are the same, ignoring case, if the 
  594.      * sequences have the same length and corresponding characters are 
  595.      * the same, ignoring case. 
  596.      *
  597.      * @param   anotherString   the <code>String</code> to compare this
  598.      *                          <code>String</code> against.
  599.      * @return  <code>true</code> if the <code>String</code>s are equal,
  600.      *          ignoring case; <code>false</code> otherwise.
  601.      * @see     java.lang.Character#toLowerCase(char)
  602.      * @see     java.lang.Character#toUpperCase(char)
  603.      */
  604.     public boolean equalsIgnoreCase(String anotherString) {
  605.     return (anotherString != null) && (anotherString.count == count) &&
  606.         regionMatches(true, 0, anotherString, 0, count);
  607.     }
  608.  
  609.     /**
  610.      * Compares two strings lexicographically. 
  611.      * The comparison is based on the Unicode value of each character in
  612.      * the strings. 
  613.      *
  614.      * @param   anotherString   the <code>String</code> to be compared.
  615.      * @return  the value <code>0</code> if the argument string is equal to
  616.      *          this string; a value less than <code>0</code> if this string
  617.      *          is lexicographically less than the string argument; and a
  618.      *          value greater than <code>0</code> if this string is
  619.      *          lexicographically greater than the string argument.
  620.      */
  621.     public int compareTo(String anotherString) {
  622.     int len1 = count;
  623.     int len2 = anotherString.count;
  624.     int n = Math.min(len1, len2);
  625.     char v1[] = value;
  626.     char v2[] = anotherString.value;
  627.     int i = offset;
  628.     int j = anotherString.offset;
  629.  
  630.     while (n-- != 0) {
  631.         char c1 = v1[i++];
  632.         char c2 = v2[j++];
  633.         if (c1 != c2) {
  634.         return c1 - c2;
  635.         }
  636.     }
  637.     return len1 - len2;
  638.     }
  639.  
  640.     /**
  641.      * Tests if two string regions are equal. 
  642.      * <p>
  643.      * If <code>toffset</code> or <code>ooffset</code> is negative, or 
  644.      * if <code>toffset</code>+<code>length</code> is greater than the 
  645.      * length of this string, or if 
  646.      * <code>ooffset</code>+<code>length</code> is greater than the 
  647.      * length of the string argument, then this method returns 
  648.      * <code>false</code>. 
  649.      *
  650.      * @param   toffset   the starting offset of the subregion in this string.
  651.      * @param   other     the string argument.
  652.      * @param   ooffset   the starting offset of the subregion in the string
  653.      *                    argument.
  654.      * @param   len       the number of characters to compare.
  655.      * @return  <code>true</code> if the specified subregion of this string
  656.      *          exactly matches the specified subregion of the string argument;
  657.      *          <code>false</code> otherwise.
  658.      */
  659.     public boolean regionMatches(int toffset, String other, int ooffset, int len) {
  660.     char ta[] = value;
  661.     int to = offset + toffset;
  662.     int tlim = offset + count;
  663.     char pa[] = other.value;
  664.     int po = other.offset + ooffset;
  665.     // Note: toffset, ooffset, or len might be near -1>>>1.
  666.     if ((ooffset < 0) || (toffset < 0) || (toffset > count - len) || (ooffset > other.count - len)) {
  667.         return false;
  668.     }
  669.     while (len-- > 0) {
  670.         if (ta[to++] != pa[po++]) {
  671.             return false;
  672.         }
  673.     }
  674.     return true;
  675.     }
  676.  
  677.     /**
  678.      * Tests if two string regions are equal. 
  679.      * <p>
  680.      * If <code>toffset</code> or <code>ooffset</code> is negative, or 
  681.      * if <code>toffset</code>+<code>length</code> is greater than the 
  682.      * length of this string, or if 
  683.      * <code>ooffset</code>+<code>length</code> is greater than the 
  684.      * length of the string argument, then this method returns 
  685.      * <code>false</code>. 
  686.      *
  687.      * @param   ignoreCase   if <code>true</code>, ignore case when comparing
  688.      *                       characters.
  689.      * @param   toffset      the starting offset of the subregion in this
  690.      *                       string.
  691.      * @param   other        the string argument.
  692.      * @param   ooffset      the starting offset of the subregion in the string
  693.      *                       argument.
  694.      * @param   len          the number of characters to compare.
  695.      * @return  <code>true</code> if the specified subregion of this string
  696.      *          matches the specified subregion of the string argument;
  697.      *          <code>false</code> otherwise. Whether the matching is exact
  698.      *          or case insensitive depends on the <code>ignoreCase</code>
  699.      *          argument.
  700.      */
  701.     public boolean regionMatches(boolean ignoreCase,
  702.                          int toffset,
  703.                            String other, int ooffset, int len) {
  704.     char ta[] = value;
  705.     int to = offset + toffset;
  706.     int tlim = offset + count;
  707.     char pa[] = other.value;
  708.     int po = other.offset + ooffset;
  709.     // Note: toffset, ooffset, or len might be near -1>>>1.
  710.     if ((ooffset < 0) || (toffset < 0) || (toffset > count - len) || (ooffset > other.count - len)) {
  711.         return false;
  712.     }
  713.     while (len-- > 0) {
  714.         char c1 = ta[to++];
  715.         char c2 = pa[po++];
  716.         if (c1 == c2)
  717.         continue;
  718.         if (ignoreCase) {
  719.         // If characters don't match but case may be ignored,
  720.         // try converting both characters to uppercase.
  721.         // If the results match, then the comparison scan should
  722.         // continue. 
  723.         char u1 = Character.toUpperCase(c1);
  724.         char u2 = Character.toUpperCase(c2);
  725.         if (u1 == u2)
  726.             continue;
  727.         // Unfortunately, conversion to uppercase does not work properly
  728.         // for the Georgian alphabet, which has strange rules about case
  729.         // conversion.  So we need to make one last check before 
  730.         // exiting.
  731.         if (Character.toLowerCase(u1) == Character.toLowerCase(u2))
  732.             continue;
  733.         }
  734.         return false;
  735.     }
  736.     return true;
  737.     }
  738.  
  739.     /**
  740.      * Tests if this string starts with the specified prefix.
  741.      *
  742.      * @param   prefix    the prefix.
  743.      * @param   toffset   where to begin looking in the string.
  744.      * @return  <code>true</code> if the character sequence represented by the
  745.      *          argument is a prefix of the substring of this object starting
  746.      *          at index <code>toffset</code>; <code>false</code> otherwise.
  747.      */
  748.     public boolean startsWith(String prefix, int toffset) {
  749.     char ta[] = value;
  750.     int to = offset + toffset;
  751.     int tlim = offset + count;
  752.     char pa[] = prefix.value;
  753.     int po = prefix.offset;
  754.     int pc = prefix.count;
  755.     // Note: toffset might be near -1>>>1.
  756.     if ((toffset < 0) || (toffset > count - pc)) {
  757.         return false;
  758.     }
  759.     while (--pc >= 0) {
  760.         if (ta[to++] != pa[po++]) {
  761.             return false;
  762.         }
  763.     }
  764.     return true;
  765.     }
  766.  
  767.     /**
  768.      * Tests if this string starts with the specified prefix.
  769.      *
  770.      * @param   prefix   the prefix.
  771.      * @return  <code>true</code> if the character sequence represented by the
  772.      *          argument is a prefix of the character sequence represented by
  773.      *          this string; <code>false</code> otherwise.
  774.      * @since   JDK1. 0
  775.      */
  776.     public boolean startsWith(String prefix) {
  777.     return startsWith(prefix, 0);
  778.     }
  779.  
  780.     /**
  781.      * Tests if this string ends with the specified suffix.
  782.      *
  783.      * @param   suffix   the suffix.
  784.      * @return  <code>true</code> if the character sequence represented by the
  785.      *          argument is a suffix of the character sequence represented by
  786.      *          this object; <code>false</code> otherwise.
  787.      */
  788.     public boolean endsWith(String suffix) {
  789.     return startsWith(suffix, count - suffix.count);
  790.     }
  791.  
  792.     /**
  793.      * Returns a hashcode for this string.
  794.      *
  795.      * @return  a hash code value for this object. 
  796.      */
  797.     public int hashCode() {
  798.     int h = 0;
  799.     int off = offset;
  800.     char val[] = value;
  801.     int len = count;
  802.  
  803.     if (len < 16) {
  804.          for (int i = len ; i > 0; i--) {
  805.          h = (h * 37) + val[off++];
  806.          }
  807.      } else {
  808.          // only sample some characters
  809.          int skip = len / 8;
  810.          for (int i = len ; i > 0; i -= skip, off += skip) {
  811.          h = (h * 39) + val[off];
  812.          }
  813.      }
  814.  
  815.     return h;
  816.     }
  817.  
  818.     /**
  819.      * Returns the index within this string of the first occurrence of the
  820.      * specified character.
  821.      *
  822.      * @param   ch   a character.
  823.      * @return  the index of the first occurrence of the character in the
  824.      *          character sequence represented by this object, or
  825.      *          <code>-1</code> if the character does not occur.
  826.      */
  827.     public int indexOf(int ch) {
  828.     return indexOf(ch, 0);
  829.     }
  830.  
  831.     /**
  832.      * Returns the index within this string of the first occurrence of the
  833.      * specified character, starting the search at the specified index.
  834.      *
  835.      * @param   ch          a character.
  836.      * @param   fromIndex   the index to start the search from.
  837.      * @return  the index of the first occurrence of the character in the
  838.      *          character sequence represented by this object that is greater
  839.      *          than or equal to <code>fromIndex</code>, or <code>-1</code>
  840.      *          if the character does not occur.
  841.      */
  842.     public int indexOf(int ch, int fromIndex) {
  843.     int max = offset + count;
  844.     char v[] = value;
  845.  
  846.     if (fromIndex < 0) {
  847.         fromIndex = 0;
  848.     } else if (fromIndex >= count) {
  849.         // Note: fromIndex might be near -1>>>1.
  850.         return -1;
  851.     }
  852.     for (int i = offset + fromIndex ; i < max ; i++) {
  853.         if (v[i] == ch) {
  854.         return i - offset;
  855.         }
  856.     }
  857.     return -1;
  858.     }
  859.  
  860.     /**
  861.      * Returns the index within this string of the last occurrence of the
  862.      * specified character.
  863.      * The String is searched backwards starting at the last character.
  864.      *
  865.      * @param   ch   a character.
  866.      * @return  the index of the last occurrence of the character in the
  867.      *          character sequence represented by this object, or
  868.      *          <code>-1</code> if the character does not occur.
  869.      */
  870.     public int lastIndexOf(int ch) {
  871.     return lastIndexOf(ch, count - 1);
  872.     }
  873.  
  874.     /**
  875.      * Returns the index within this string of the last occurrence of the
  876.      * specified character, searching backward starting at the specified index.
  877.      *
  878.      * @param   ch          a character.
  879.      * @param   fromIndex   the index to start the search from.
  880.      * @return  the index of the last occurrence of the character in the
  881.      *          character sequence represented by this object that is less
  882.      *          than or equal to <code>fromIndex</code>, or <code>-1</code>
  883.      *          if the character does not occur before that point.
  884.      */
  885.     public int lastIndexOf(int ch, int fromIndex) {
  886.     int min = offset;
  887.     char v[] = value;
  888.     
  889.     for (int i = offset + ((fromIndex >= count) ? count - 1 : fromIndex) ; i >= min ; i--) {
  890.         if (v[i] == ch) {
  891.         return i - offset;
  892.         }
  893.     }
  894.     return -1;
  895.     }
  896.  
  897.     /**
  898.      * Returns the index within this string of the first occurrence of the
  899.      * specified substring.
  900.      *
  901.      * @param   str   any string.
  902.      * @return  if the string argument occurs as a substring within this
  903.      *          object, then the index of the first character of the first
  904.      *          such substring is returned; if it does not occur as a
  905.      *          substring, <code>-1</code> is returned.
  906.      */
  907.     public int indexOf(String str) {
  908.     return indexOf(str, 0);
  909.     }
  910.  
  911.     /**
  912.      * Returns the index within this string of the first occurrence of the
  913.      * specified substring, starting at the specified index.
  914.      *
  915.      * @param   str         the substring to search for.
  916.      * @param   fromIndex   the index to start the search from.
  917.      * @return  If the string argument occurs as a substring within this
  918.      *          object at a starting index no smaller than
  919.      *          <code>fromIndex</code>, then the index of the first character
  920.      *          of the first such substring is returned. If it does not occur
  921.      *          as a substring starting at <code>fromIndex</code> or beyond,
  922.      *          <code>-1</code> is returned.
  923.      */
  924.     public int indexOf(String str, int fromIndex) {
  925.         char v1[] = value;
  926.         char v2[] = str.value;
  927.         int max = offset + (count - str.count);
  928.     if (fromIndex >= count) {
  929.         /* Note: fromIndex might be near -1>>>1 */
  930.         return -1;
  931.     }
  932.         if (fromIndex < 0) {
  933.             fromIndex = 0;
  934.         }
  935.     if (str.count == 0) {
  936.         return fromIndex;
  937.     }
  938.  
  939.         int strOffset = str.offset;
  940.         char first  = v2[strOffset];
  941.         int i = offset + fromIndex;
  942.  
  943.     startSearchForFirstChar:
  944.         while (true) {
  945.  
  946.         /* Look for first character. */
  947.         while (i <= max && v1[i] != first) {
  948.         i++;
  949.         }
  950.         if (i > max) {
  951.         return -1;
  952.         }
  953.  
  954.         /* Found first character, now look at the rest of v2 */
  955.         int j = i + 1;
  956.         int end = j + str.count - 1;
  957.         int k = strOffset + 1;
  958.         while (j < end) {
  959.         if (v1[j++] != v2[k++]) {
  960.             i++;
  961.             /* Look for str's first char again. */
  962.             continue startSearchForFirstChar;
  963.         }
  964.         }
  965.         return i - offset;    /* Found whole string. */
  966.         }
  967.     }
  968.  
  969.     /**
  970.      * Returns the index within this string of the rightmost occurrence
  971.      * of the specified substring.  The rightmost empty string "" is
  972.      * considered to occur at the index value <code>this.length()</code>.
  973.      *
  974.      * @param   str   the substring to search for.
  975.      * @return  if the string argument occurs one or more times as a substring
  976.      *          within this object, then the index of the first character of
  977.      *          the last such substring is returned. If it does not occur as
  978.      *          a substring, <code>-1</code> is returned.
  979.      */
  980.     public int lastIndexOf(String str) {
  981.     return lastIndexOf(str, count);
  982.     }
  983.  
  984.     /**
  985.      * Returns the index within this string of the last occurrence of
  986.      * the specified substring.
  987.      * The returned index indicates the start of the substring, and it
  988.      * must be equal to or less than <code>fromIndex</code>.
  989.      *
  990.      * @param   str         the substring to search for.
  991.      * @param   fromIndex   the index to start the search from.
  992.      * @return  If the string argument occurs one or more times as a substring
  993.      *          within this object at a starting index no greater than
  994.      *          <code>fromIndex</code>, then the index of the first character of
  995.      *          the last such substring is returned. If it does not occur as a
  996.      *          substring starting at <code>fromIndex</code> or earlier,
  997.      *          <code>-1</code> is returned.
  998.      */
  999.     public int lastIndexOf(String str, int fromIndex) {
  1000.         /* 
  1001.      * Check arguments; return immediately where possible. For
  1002.      * consistency, don't check for null str.
  1003.      */
  1004.         int rightIndex = count - str.count;
  1005.     if (fromIndex < 0) {
  1006.         return -1;
  1007.     }
  1008.     if (fromIndex > rightIndex) {
  1009.         fromIndex = rightIndex;
  1010.     }
  1011.     /* Empty string always matches. */
  1012.     if (str.count == 0) {
  1013.         return fromIndex;
  1014.     }
  1015.  
  1016.     char v1[] = value;
  1017.     char v2[] = str.value;
  1018.     int strLastIndex = str.offset + str.count - 1;
  1019.     char strLastChar = v2[strLastIndex];
  1020.     int min = offset + str.count - 1;
  1021.     int i = min + fromIndex;
  1022.  
  1023.     startSearchForLastChar:
  1024.     while (true) {
  1025.  
  1026.         /* Look for the last character */
  1027.         while (i >= min && v1[i] != strLastChar) {
  1028.         i--;
  1029.         }
  1030.         if (i < min) {
  1031.         return -1;
  1032.         }
  1033.  
  1034.         /* Found last character, now look at the rest of v2. */
  1035.         int j = i - 1;
  1036.         int start = j - (str.count - 1);
  1037.         int k = strLastIndex - 1;
  1038.  
  1039.         while (j > start) {
  1040.             if (v1[j--] != v2[k--]) {
  1041.             i--;
  1042.             /* Look for str's last char again. */
  1043.             continue startSearchForLastChar;
  1044.         }
  1045.         }
  1046.  
  1047.         return start - offset + 1;    /* Found whole string. */
  1048.     }
  1049.     }
  1050.  
  1051.     /**
  1052.      * Returns a new string that is a substring of this string. The 
  1053.      * substring begins at the specified index and extends to the end of 
  1054.      * this string. 
  1055.      *
  1056.      * @param      beginIndex   the beginning index, inclusive.
  1057.      * @return     the specified substring.
  1058.      * @exception  StringIndexOutOfBoundsException  if the
  1059.      *             <code>beginIndex</code> is out of range.
  1060.      */
  1061.     public String substring(int beginIndex) {
  1062.     return substring(beginIndex, length());
  1063.     }
  1064.  
  1065.     /**
  1066.      * Returns a new string that is a substring of this string. The 
  1067.      * substring begins at the specified <code>beginIndex</code> and 
  1068.      * extends to the character at index <code>endIndex - 1</code>. 
  1069.      *
  1070.      * @param      beginIndex   the beginning index, inclusive.
  1071.      * @param      endIndex     the ending index, exclusive.
  1072.      * @return     the specified substring.
  1073.      * @exception  StringIndexOutOfBoundsException  if the
  1074.      *             <code>beginIndex</code> or the <code>endIndex</code> is
  1075.      *             out of range.
  1076.      */
  1077.     public String substring(int beginIndex, int endIndex) {
  1078.     if (beginIndex < 0) {
  1079.         throw new StringIndexOutOfBoundsException(beginIndex);
  1080.     } 
  1081.     if (endIndex > count) {
  1082.         throw new StringIndexOutOfBoundsException(endIndex);
  1083.     }
  1084.     if (beginIndex > endIndex) {
  1085.         throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
  1086.     }
  1087.     return ((beginIndex == 0) && (endIndex == count)) ? this :
  1088.         new String(offset + beginIndex, endIndex - beginIndex, value);
  1089.     }
  1090.  
  1091.     /**
  1092.      * Concatenates the specified string to the end of this string. 
  1093.      * <p>
  1094.      * If the length of the argument string is <code>0</code>, then this 
  1095.      * object is returned. 
  1096.      *
  1097.      * @param   str   the <code>String</code> that is concatenated to the end
  1098.      *                of this <code>String</code>.
  1099.      * @return  a string that represents the concatenation of this object's
  1100.      *          characters followed by the string argument's characters.
  1101.      */
  1102.     public String concat(String str) {
  1103.     int otherLen = str.length();
  1104.     if (otherLen == 0) {
  1105.         return this;
  1106.     }
  1107.     char buf[] = new char[count + otherLen];
  1108.     getChars(0, count, buf, 0);
  1109.     str.getChars(0, otherLen, buf, count);
  1110.     return new String(0, count + otherLen, buf);
  1111.     }
  1112.  
  1113.     /**
  1114.      * Returns a new string resulting from replacing all occurrences of 
  1115.      * <code>oldChar</code> in this string with <code>newChar</code>. 
  1116.      * <p>
  1117.      * If the character <code>oldChar</code> does not occur in the 
  1118.      * character sequence represented by this object, then this string is 
  1119.      * returned. 
  1120.      *
  1121.      * @param   oldChar   the old character.
  1122.      * @param   newChar   the new character.
  1123.      * @return  a string derived from this string by replacing every
  1124.      *          occurrence of <code>oldChar</code> with <code>newChar</code>.
  1125.      */
  1126.     public String replace(char oldChar, char newChar) {
  1127.     if (oldChar != newChar) {
  1128.         int len = count;
  1129.         int i = -1;
  1130.         char[] val = value; /* avoid getfield opcode */
  1131.         int off = offset;   /* avoid getfield opcode */
  1132.  
  1133.         while (++i < len) {
  1134.         if (val[off + i] == oldChar) {
  1135.             break;
  1136.         }
  1137.         }
  1138.         if (i < len) {
  1139.         char buf[] = new char[len];
  1140.         for (int j = 0 ; j < i ; j++) {
  1141.             buf[j] = val[off+j];
  1142.         }
  1143.         while (i < len) {
  1144.             char c = val[off + i];
  1145.             buf[i] = (c == oldChar) ? newChar : c;
  1146.             i++;
  1147.         }
  1148.         return new String(0, len, buf);
  1149.         }
  1150.     }
  1151.     return this;
  1152.     }
  1153.  
  1154.     /**
  1155.      * Converts all of the characters in this <code>String</code> to lower
  1156.      * case using the rules of the given locale.
  1157.      * @param locale use the case transformation rules for this locale
  1158.      * @return the String, converted to lowercase.
  1159.      * @see     java.lang.Character#toLowerCase(char)
  1160.      * @see     java.lang.String#toUpperCase()
  1161.      * @since   JDK1.1
  1162.      */
  1163.     public String toLowerCase(Locale locale) {
  1164.         char[] result = new char[count];
  1165.         int i;
  1166.         int len = count;
  1167.     int off = offset;       /* avoid getfield opcode */
  1168.     char[] val = value;        /* avoid getfield opcode */
  1169.       
  1170.         if (locale.getLanguage().equals("tr")) {
  1171.             // special loop for Turkey
  1172.         for (i = 0; i < len; ++i) {
  1173.                 char ch = val[off+i];
  1174.                 if (ch == 'I') {
  1175.                     result[i] = '\u0131'; // dotless small i
  1176.                     continue;
  1177.                 }
  1178.                 if (ch == '\u0130') {       // dotted I
  1179.                     result[i] = 'i';      // dotted i
  1180.                     continue;
  1181.                 }
  1182.                 result[i] = Character.toLowerCase(ch);
  1183.             }
  1184.         } else {
  1185.             // normal, fast loop
  1186.             for (i = 0; i < len; ++i) {
  1187.                 result[i] = Character.toLowerCase(val[off+i]);
  1188.             }
  1189.         }
  1190.         return new String(result);
  1191.     }
  1192.  
  1193.     /**
  1194.      * Converts this <code>String</code> to lowercase. 
  1195.      * <p>
  1196.      * If no character in the string has a different lowercase version, 
  1197.      * based on calling the <code>toLowerCase</code> method defined by 
  1198.      * <code>Character</code>, then the original string is returned. 
  1199.      * <p>
  1200.      * Otherwise, a new string is allocated, whose length is identical 
  1201.      * to this string, and such that each character that has a different 
  1202.      * lowercase version is mapped to this lowercase equivalent. 
  1203.      *
  1204.      * @return  the string, converted to lowercase.
  1205.      * @see     java.lang.Character#toLowerCase(char)
  1206.      * @see     java.lang.String#toUpperCase()
  1207.      */
  1208.     public String toLowerCase() {
  1209.         return toLowerCase( Locale.getDefault() );
  1210.     }
  1211.  
  1212.     /**
  1213.      * Converts all of the characters in this <code>String</code> to upper
  1214.      * case using the rules of the given locale.
  1215.      * @param locale use the case transformation rules for this locale
  1216.      * @return the String, converted to uppercase.
  1217.      * @see     java.lang.Character#toUpperCase(char)
  1218.      * @see     java.lang.String#toLowerCase(char)
  1219.      * @since   JDK1.1
  1220.      */
  1221.     public String toUpperCase(Locale locale) {
  1222.         char[] result = new char[count]; /* warning: might grow! */
  1223.         int i;
  1224.     int resultOffset = 0;  /* result might grow, so i+resultOffset
  1225.                 * gives correct write location in result
  1226.                 */
  1227.     int len = count;
  1228.         int off = offset;       /* avoid getfield opcode */
  1229.     char[] val = value;        /* avoid getfield opcode */
  1230.         if (locale.getLanguage().equals("tr")) {
  1231.             // special loop for Turkey
  1232.         for (i = 0; i < len; ++i) {
  1233.                 char ch = val[off+i];
  1234.                 if (ch == 'i') {
  1235.             result[i+resultOffset] = '\u0130';  // dotted cap i
  1236.                     continue;
  1237.                 }
  1238.                 if (ch == '\u0131') {                   // dotless i
  1239.                     result[i+resultOffset] = 'I';       // cap I
  1240.                     continue;
  1241.                 }
  1242.                 if (ch == '\u00DF') {                   // sharp s
  1243.             /* Grow result. */
  1244.             char[] result2 = new char[result.length + 1];
  1245.             System.arraycopy(result, 0, result2, 0,
  1246.                      i + 1 + resultOffset);
  1247.                     result2[i+resultOffset] = 'S';
  1248.             resultOffset++;
  1249.             result2[i+resultOffset] = 'S';
  1250.             result = result2;
  1251.                     continue;
  1252.                 }
  1253.                 result[i+resultOffset] = Character.toUpperCase(ch);
  1254.             }
  1255.         } else {
  1256.             // normal, fast loop
  1257.             for (i = 0; i < len; ++i) {
  1258.                 char ch = val[off+i];
  1259.                 if (ch == '\u00DF') { // sharp s
  1260.             /* Grow result. */
  1261.             char[] result2 = new char[result.length + 1];
  1262.             System.arraycopy(result, 0, result2, 0,
  1263.                      i + 1 + resultOffset);
  1264.                     result2[i+resultOffset] = 'S';
  1265.             resultOffset++;
  1266.             result2[i+resultOffset] = 'S';
  1267.             result = result2;
  1268.                     continue;
  1269.                 }
  1270.                 result[i+resultOffset] = Character.toUpperCase(ch);
  1271.             }
  1272.         }
  1273.         return new String(result);
  1274.     }
  1275.     
  1276.     /**
  1277.      * Converts this string to uppercase. 
  1278.      * <p>
  1279.      * If no character in this string has a different uppercase version, 
  1280.      * based on calling the <code>toUpperCase</code> method defined by 
  1281.      * <code>Character</code>, then the original string is returned. 
  1282.      * <p>
  1283.      * Otherwise, a new string is allocated, whose length is identical 
  1284.      * to this string, and such that each character that has a different 
  1285.      * uppercase version is mapped to this uppercase equivalent. 
  1286.      *
  1287.      * @return  the string, converted to uppercase.
  1288.      * @see     java.lang.Character#toUpperCase(char)
  1289.      * @see     java.lang.String#toLowerCase()
  1290.      */
  1291.     public String toUpperCase() {
  1292.         return toUpperCase( Locale.getDefault() );
  1293.     }
  1294.  
  1295.     /**
  1296.      * Removes white space from both ends of this string. 
  1297.      * <p>
  1298.      * All characters that have codes less than or equal to 
  1299.      * <code>'\u0020'</code> (the space character) are considered to be 
  1300.      * white space. 
  1301.      *
  1302.      * @return  this string, with white space removed from the front and end.
  1303.      */
  1304.     public String trim() {
  1305.     int len = count;
  1306.     int st = 0;
  1307.     int off = offset;      /* avoid getfield opcode */
  1308.     char[] val = value;    /* avoid getfield opcode */
  1309.  
  1310.     while ((st < len) && (val[off + st] <= ' ')) {
  1311.         st++;
  1312.     }
  1313.     while ((st < len) && (val[off + len - 1] <= ' ')) {
  1314.         len--;
  1315.     }
  1316.     return ((st > 0) || (len < count)) ? substring(st, len) : this;
  1317.     }
  1318.  
  1319.     /**
  1320.      * This object (which is already a string!) is itself returned. 
  1321.      *
  1322.      * @return  the string itself.
  1323.      */
  1324.     public String toString() {
  1325.     return this;
  1326.     }
  1327.  
  1328.     /**
  1329.      * Converts this string to a new character array.
  1330.      *
  1331.      * @return  a newly allocated character array whose length is the length
  1332.      *          of this string and whose contents are initialized to contain
  1333.      *          the character sequence represented by this string.
  1334.      */
  1335.     public char[] toCharArray() {
  1336.     int max = length();
  1337.     char result[] = new char[max];
  1338.     getChars(0, max, result, 0);
  1339.     return result;
  1340.     }
  1341.  
  1342.     /**
  1343.      * Returns the string representation of the <code>Object</code> argument. 
  1344.      *
  1345.      * @param   obj   an <code>Object</code>.
  1346.      * @return  if the argument is <code>null</code>, then a string equal to
  1347.      *          <code>"null"</code>; otherwise, the value of
  1348.      *          <code>obj.toString()</code> is returned.
  1349.      * @see     java.lang.Object#toString()  
  1350.      */
  1351.     public static String valueOf(Object obj) {
  1352.     return (obj == null) ? "null" : obj.toString();
  1353.     }
  1354.  
  1355.     /**
  1356.      * Returns the string representation of the <code>char</code> array
  1357.      * argument. 
  1358.      *
  1359.      * @param   data   a <code>char</code> array.
  1360.      * @return  a newly allocated string representing the same sequence of
  1361.      *          characters contained in the character array argument.
  1362.      */
  1363.     public static String valueOf(char data[]) {
  1364.     return new String(data);
  1365.     }
  1366.  
  1367.     /**
  1368.      * Returns the string representation of a specific subarray of the 
  1369.      * <code>char</code> array argument. 
  1370.      * <p>
  1371.      * The <code>offset</code> argument is the index of the first 
  1372.      * character of the subarray. The <code>count</code> argument 
  1373.      * specifies the length of the subarray. 
  1374.      *
  1375.      * @param   data     the character array.
  1376.      * @param   offset   the initial offset into the value of the
  1377.      *                  <code>String</code>.
  1378.      * @param   count    the length of the value of the <code>String</code>.
  1379.      * @return  a newly allocated string representing the sequence of
  1380.      *          characters contained in the subarray of the character array
  1381.      *          argument.
  1382.      */
  1383.     public static String valueOf(char data[], int offset, int count) {
  1384.     return new String(data, offset, count);
  1385.     }
  1386.     
  1387.     /**
  1388.      * Returns a String that is equivalent to the specified character array.
  1389.      * It creates a new array and copies the characters into it.
  1390.      *
  1391.      * @param   data     the character array.
  1392.      * @param   offset   initial offset of the subarray.
  1393.      * @param   count    length of the subarray.
  1394.      * @return  a <code>String</code> that contains the characters of the
  1395.      *          specified subarray of the character array.
  1396.      */
  1397.     public static String copyValueOf(char data[], int offset, int count) {
  1398.     // All public String constructors now copy the data.
  1399.     return new String(data, offset, count);
  1400.     }
  1401.  
  1402.     /**
  1403.      * Returns a String that is equivalent to the specified character array.
  1404.      * It creates a new array and copies the characters into it.
  1405.      *
  1406.      * @param   data   the character array.
  1407.      * @return  a <code>String</code> that contains the characters of the
  1408.      *          character array.
  1409.      */
  1410.     public static String copyValueOf(char data[]) {
  1411.     return copyValueOf(data, 0, data.length);
  1412.     }
  1413.  
  1414.     /**
  1415.      * Returns the string representation of the <code>boolean</code> argument. 
  1416.      *
  1417.      * @param   b   a <code>boolean</code>.
  1418.      * @return  if the argument is <code>true</code>, a string equal to
  1419.      *          <code>"true"</code> is returned; otherwise, a string equal to
  1420.      *          <code>"false"</code> is returned.
  1421.      */
  1422.     public static String valueOf(boolean b) {
  1423.     return b ? "true" : "false";
  1424.     }
  1425.  
  1426.     /**
  1427.      * Returns the string representation of the <code>char</code> * argument. 
  1428.      *
  1429.      * @param   c   a <code>char</code>.
  1430.      * @return  a newly allocated string of length <code>1</code> containing
  1431.      *          as its single character the argument <code>c</code>.
  1432.      */
  1433.     public static String valueOf(char c) {
  1434.     char data[] = {c};
  1435.     return new String(0, 1, data);
  1436.     }
  1437.  
  1438.     /**
  1439.      * Returns the string representation of the <code>int</code> argument. 
  1440.      * <p>
  1441.      * The representation is exactly the one returned by the 
  1442.      * <code>Integer.toString</code> method of one argument. 
  1443.      *
  1444.      * @param   i   an <code>int</code>.
  1445.      * @return  a newly allocated string containing a string representation of
  1446.      *          the <code>int</code> argument.
  1447.      * @see     java.lang.Integer#toString(int, int)
  1448.      */
  1449.     public static String valueOf(int i) {
  1450.         return Integer.toString(i, 10);
  1451.     }
  1452.  
  1453.     /**
  1454.      * Returns the string representation of the <code>long</code> argument. 
  1455.      * <p>
  1456.      * The representation is exactly the one returned by the 
  1457.      * <code>Long.toString</code> method of one argument. 
  1458.      *
  1459.      * @param   l   a <code>long</code>.
  1460.      * @return  a newly allocated string containing a string representation of
  1461.      *          the <code>long</code> argument.
  1462.      * @see     java.lang.Long#toString(long)
  1463.      */
  1464.     public static String valueOf(long l) {
  1465.         return Long.toString(l, 10);
  1466.     }
  1467.  
  1468.     /**
  1469.      * Returns the string representation of the <code>float</code> argument. 
  1470.      * <p>
  1471.      * The representation is exactly the one returned by the 
  1472.      * <code>Float.toString</code> method of one argument. 
  1473.      *
  1474.      * @param   f   a <code>float</code>.
  1475.      * @return  a newly allocated string containing a string representation of
  1476.      *          the <code>float</code> argument.
  1477.      * @see     java.lang.Float#toString(float)
  1478.      */
  1479.     public static String valueOf(float f) {
  1480.     return Float.toString(f);
  1481.     }
  1482.  
  1483.     /**
  1484.      * Returns the string representation of the <code>double</code> argument. 
  1485.      * <p>
  1486.      * The representation is exactly the one returned by the 
  1487.      * <code>Double.toString</code> method of one argument. 
  1488.      *
  1489.      * @param   d   a <code>double</code>.
  1490.      * @return  a newly allocated string containing a string representation of
  1491.      *          the <code>double</code> argument.
  1492.      * @see     java.lang.Double#toString(double)
  1493.      */
  1494.     public static String valueOf(double d) {
  1495.     return Double.toString(d);
  1496.     }
  1497.  
  1498.     /**
  1499.      * Returns a canonical representation for the string object. 
  1500.      * <p>
  1501.      * If <code>s</code> and <code>t</code> are strings such that 
  1502.      * <code>s.equals(t)</code>, it is guaranteed that<br>
  1503.      * <code>s.intern() == t.intern(). </code> 
  1504.      *
  1505.      * @return  a string that has the same contents as this string, but is
  1506.      *          guaranteed to be from a pool of unique strings.
  1507.      */
  1508.     public native String intern();
  1509.  
  1510.     /**
  1511.      * Returns the length of this string's UTF encoded form.
  1512.      */
  1513.     int utfLength() {
  1514.     int limit = offset + count;
  1515.     int utflen = 0;
  1516.     char[] val = value;
  1517.  
  1518.     for (int i = offset; i < limit; i++) {
  1519.         int c = val[i];
  1520.         if ((c >= 0x0001) && (c <= 0x007F)) {
  1521.         utflen++;
  1522.         } else if (c > 0x07FF) {
  1523.         utflen += 3;
  1524.         } else {
  1525.         utflen += 2;
  1526.         }
  1527.     }
  1528.     return utflen;
  1529.     }
  1530.  
  1531. }
  1532.